﻿using Serilog;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting.Json;
using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.File;
using Serilog.Sinks.SystemConsole.Themes;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Sustainalytics.Admin.Synchronization.Utility;

namespace Sustainalytics.Accounts.BusinessLogic
{ 
    public class AccountsServiceSerilog
    {
        public static Lazy<AccountsServiceSerilog> _lazyLog = new Lazy<AccountsServiceSerilog>(InitLog, LazyThreadSafetyMode.ExecutionAndPublication);
        private readonly ILogger _logger;

        public static AccountsServiceSerilog Log
        {
            get
            {
                return _lazyLog.Value;
            }
        }

        public static AccountsServiceSerilog InitLog()
        {
            var log = new AccountsServiceSerilog();

            log.Ping();

            return log;

        }

        public AccountsServiceSerilog()
        {
            var loggerConfig = new LoggerConfiguration()
                  .MinimumLevel.Debug()
                  .WriteTo.Console(theme: SystemConsoleTheme.Literate)
                  .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200")) 
                  {
                      IndexFormat = "testaccounts-{0:yyyy.MM.dd}",
                      AutoRegisterTemplate = true,
                      RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
                      FailureCallback = e => Console.WriteLine("Unable to submit event " + e.MessageTemplate),
                      EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog |
                                         EmitEventFailureHandling.WriteToFailureSink |
                                         EmitEventFailureHandling.RaiseCallback,
                      FailureSink = new FileSink("../failuresAccountService-"+ DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss") + ".txt", new JsonFormatter(), null)
                  });
            _logger = loggerConfig.CreateLogger();

            SelfLog.Enable(Console.Error);
        }

        public void ApplicationStartError(Exception e)
        {
            if (e == null)
                return;

            if(_logger.IsEnabled(LogEventLevel.Error))
                ApplicationStartException(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));

        }
   
        private void ApplicationStartException(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            var eventId = 23;

            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("ApplicationStartException {0}, {1}, {2}, {3}", eventId, exceptionType, exceptionMessage, exceptionInformation);
        }


        public void ApplicationUnhandledException(Exception e)
        {
            if (e == null)
                return;

            if (_logger.IsEnabled(LogEventLevel.Error))
                ApplicationUnhandledException(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));
        }

      
        private void ApplicationUnhandledException(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            var eventId = 25;

            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("ApplicationUnhandledException {0}, {1}, {2}, {3}", eventId, exceptionType, exceptionMessage, exceptionInformation);
        }

        public void ApplicationStopError(Exception e)
        {
            if (e == null)
                return;

            if (_logger.IsEnabled(LogEventLevel.Error))
                ApplicationStopError(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));
        }

        private void ApplicationStopError(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            var eventId = 24;

            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("ApplicationStopError {0}, {1}, {2}, {3}", eventId, exceptionType, exceptionMessage, exceptionInformation);
        }

        public void Ping()
        {
            var eventId = 1;

            if (_logger.IsEnabled(LogEventLevel.Debug))
                _logger.Debug("Ping {0}", eventId);
        }

        public void GetAccounts(string status, string searchText, int skip, int take)
        {
            var eventId = 2;

            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetAccounts {0}, {1}, {2}, {3}", eventId,status, searchText, skip, take);
        }

        public void GetAccountsError(string status, string searchText, int skip, int take, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetAccountsError(status, searchText, skip, take, exception.ToString());
            }
        }

        public void GetAccountsError(string status, string searchText, int skip, int take, string exceptionMessage)
        {
            var eventId = 3;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetAccountsError {0}, {1}, {2}, {3}, {4}, {5}", eventId, status, searchText, skip, take, exceptionMessage);
        }

        public void GetAccount(Guid accountId)
        {
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetAccount {0}", accountId);
        }

        public void GetAccountError(Guid accountId, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetAccountError(accountId, exception.ToString());
            }
        }

        public void GetAccountError(Guid accountId, string exceptionMessage)
        {
            var eventId = 5;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetAccountError {0}, {1}, {2}", eventId, accountId, exceptionMessage);
        }


        public void GetUsers(string accountIds, string status, string searchText, int skip, int take)
        {
            var eventId = 6;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUsers {0}, {1}, {2}, {3}, {4}, {5}", eventId, accountIds, status, searchText, skip, take);
        }

        public void GetUsersError(string accountIds, string status, string searchText, int skip, int take, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetUsersError(accountIds, status, searchText, skip, take, exception.ToString());
            }
        }

        public void GetUsersError(string accountIds, string status, string searchText, int skip, int take, string exceptionMessage)
        {
            var eventId = 7;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetUsersError {0}, {1}, {2}, {3}, {4}, {5}, {6}", eventId, accountIds, status, searchText, skip, take, exceptionMessage);
        }

        public void GetUser(Guid userId)
        {
            var eventId = 8;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUser {0}, {1}", eventId, userId);
        }

        public void GetUserError(Guid userId, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "exception");
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                this.GetUserError(userId, exception.ToString());
            }
        }

        public void GetUserError(Guid userId, string exceptionMessage)
        {
            var eventId = 9;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUserError {0}, {1}, {2}", eventId, userId, exceptionMessage);
        }

        public void GetClientUserByUserId(Guid userId)
        {
            var eventId = 10;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetClientUserByUserId {0}, {1}", eventId, userId);
        }

        public void ResetPasswords(string userIds)
        {
            var eventId = 11;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information(" ResetPassword {0}, {1}", eventId, userIds);
        }

        public void ResetPasswordsError(string userIds, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.ResetPasswordsError(userIds, exception.ToString());
            }
        }

        public void ResetPasswordsError(string userIds, string exceptionMessage)
        {
            var eventId = 12;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("ResetPasswordsError {0}, {1}, {2}", eventId, userIds, exceptionMessage);
        }

        public void GetAccountUsers(Guid accountId)
        {
            var eventId = 13;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetAccountsUsers {0}, {1}", eventId, accountId);
        }

        public void GetAccountUsersError(Guid accountId, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "Exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetAccountUsersError(accountId, exception.ToString());
            }
        }

        public void GetAccountUsersError(Guid accountId, string exceptionMessage)
        {
            var eventId = 14;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetAccountUsersError {0}, {1}, {2}", eventId, accountId, exceptionMessage);
        }

        public void GetUsersTotalCount(string accountIds, string status, string searchText)
        {
            var eventId = 15;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUsersTotalCount {0}, {1}, {2}, {3}", eventId, accountIds, status, searchText );
        }

        public void GetUsersTotalCountError(string accountIds, string status, string searchText, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "Exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetUsersTotalCountError(accountIds, status, searchText, exception.ToString());
            }
        }

        public void GetUsersTotalCountError(string accountIds, string status, string searchText, string exceptionMessage)
        {
            var eventId = 16;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("{0}, {1}, {2}, {3}, {4}", eventId, accountIds, status, searchText, exceptionMessage);
        }

        public void GetAccountsTotalCount(string status, string searchText)
        {
            var eventId = 17;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUsersTotalCountError {0}, {1}, {2}", eventId, status, searchText);
        }

        public void GetAccountsTotalCountError(string status, string searchText, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "Exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetAccountsTotalCountError(status, searchText, exception.ToString());
            }
        }

        public void GetAccountsTotalCountError(string status, string searchText, string exceptionMessage)
        {
            var eventId = 18;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetAccountsTotalCountError {0}, {1}, {2}, {3}", eventId, status, searchText, exceptionMessage);
        }

        public void GetAccountsLastSyncCrm()
        {
            var eventId = 19;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetAccountsLastSyncCrm {0}", eventId);
        }

        public void GetAccountsLastSyncCrmError(Exception exception)
        {
            Guard.ArgumentNotNull(exception, "Exception");
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                this.GetAccountsLastSyncCrmError(exception.ToString());
            }
        }

        public void GetAccountsLastSyncCrmError(string exceptionMessage)
        {
            var eventId = 20;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetAccountsLastSyncCrmError {0}, {1}", eventId, exceptionMessage);
        }

        public void GetUsersLastSyncCrm(string status, string searchText)
        {
            var eventId = 21;
            if (_logger.IsEnabled(LogEventLevel.Information))
                _logger.Information("GetUsersLastSyncCrm {0}, {1}, {2}", eventId, status, searchText);
        }

        public void GetUsersLastSyncCrmError(string status, string searchText, Exception exception)
        {
            Guard.ArgumentNotNull(exception, "Exception");
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                this.GetUsersLastSyncCrmError(status, searchText, exception.ToString());
            }
        }
        public void GetUsersLastSyncCrmError(string status, string searchText, string exceptionMessage)
        {
            var eventId = 22;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("GetUsersLastSyncCrmError {0}, {1}, {2}, {3}", eventId, status, searchText, exceptionMessage);
        }
    }
}
